import {
	getUUID,
	cmp
} from "../../utils/index.js";
import {
	ENUM_NOTIFICATION_TYPE
} from "../../../static/enum.js"
import NotificationObserver from "./notificationObserver.js";
/**
 * ############## 通知对象 ###############
 */
module.exports = class Notification {
	name = ""; // notification 名称/标识
	notificationType = ENUM_NOTIFICATION_TYPE.NORMAL; // 通知模式类型
	notificationObserverList = []; // 监听该通知的 监听者对象列表
	/**
	 * 通知对象 构造器
	 * @param {string} name 名称
	 * @param {ENUM_NOTIFICATION_TYPE} notificationType 类型
	 */
	constructor(name, notificationType = ENUM_NOTIFICATION_TYPE.NORMAL) {
		this.name = name; // notification 名称/标识
		this.notificationType = notificationType; // 通知模式类型
		this.notificationObserverList = []; // 监听该通知的 监听者对象列表
	}
	// 移除观察者
	removeObserver(observerSymbol) {
		// 判断传入的参数是否为 NotificationObserver 对象
		if (observerSymbol === null || observerSymbol === undefined) {
			// 抛出错误
			throw new Error('removeObserver 请传入 observerSymbol');
		}
		// 判断观察者列表是否为空
		if (this.notificationObserverList.length == 0) {
			// 如果为空，直接返回
			return;
		}
		// 定义要移除的索引
		let removeIndex = -1;
		// 遍历观察者列表
		this.notificationObserverList.forEach((item, index) => {
			// 判断当前项的观察者符号是否与传入的观察者符号相等
			if (cmp(item.observerSymbol, observerSymbol)) {
				// 如果相等，将索引赋值给 removeIndex
				removeIndex = index;
			}
		});
		// 如果 removeIndex 不为 -1，说明找到了要移除的观察者
		if (removeIndex != -1) {
			// 从观察者列表中移除该观察者
			this.notificationObserverList.splice(removeIndex, 1);
		}
	}

	// 移除所有观察者
	removeAllObserver() {
		// 如果观察者列表为空，则直接返回
		if (this.notificationObserverList.length == 0) {
			return;
		}
		// 将观察者列表置空
		this.notificationObserverList = [];
	}

	/**
	 * 添加监听对象
	 * @param {object} observer 监听对象
	 * @returns 返回 监听者标志
	 */
	addObserver(selector, observerSymbol) {
		// 如果observerSymbol为null或undefined，则调用getUUID()函数生成一个UUID
		if (observerSymbol === null || observerSymbol === undefined) {
			observerSymbol = getUUID();
		}
		let observer = new NotificationObserver(selector, observerSymbol);
		switch (this.notificationType) {
			case ENUM_NOTIFICATION_TYPE.NORMAL: // 正常监听模式
			{
				// 监听列表为空，直接插入监听列表
				if (this.notificationObserverList.length == 0) {
					this.notificationObserverList.push(observer);
					break;
				}
				// 监听列表不为空，先查找监听列表是否有该对象
				let insertIndex = -1;
				this.notificationObserverList.forEach((item, index) => {
					if (cmp(item.observerSymbol, observer.observerSymbol)) {
						insertIndex = index;
					}
				});
				if (insertIndex == -1) { // 如果没有该对象，列表插入
					this.notificationObserverList.push(observer);
				} else { // 如果有，进行替换
					this.notificationObserverList[insertIndex] = observer;
				}
				break;
			}
			case ENUM_NOTIFICATION_TYPE.FRIST: // 单次监听模式，只保存第一监听者
			{
				// 监听列表是否为空， 为空插入监听者， 不为空不进行操作，插入失败
				if (this.notificationObserverList.length == 0) {
					this.notificationObserverList = [observer];
				}
				break;
			}
			case ENUM_NOTIFICATION_TYPE.LAST: // 仅通知最新监听者模式，只有监听者列表最后一位才会响应广播通知，不要在异步中操作添加和移除通知，存在通知错误监听者的风险
			{
				// 监听列表为空，直接插入
				if (this.notificationObserverList.length == 0) {
					this.notificationObserverList.push(observer);
					break;
				}
				// 监听列表不为空，查找监听者是否存在于监听列表中
				let insertIndex = -1;
				this.notificationObserverList.forEach((item, index) => {
					if (cmp(item.observerSymbol, observer.observerSymbol)) {
						insertIndex = index;
					}
				});
				if (insertIndex == -1) { // 不存在，推入列表最后
					this.notificationObserverList.push(observer);
				} else {
					// 存在，取出对应的值并插入到监听者列表最后一位
					this.notificationObserverList.push(this.notificationObserverList.splice(insertIndex, 1)[0]);
				}
				break;
			}
			default:
				throw new Error("未知的通知类型");
		}
		return observerSymbol;
	}
}